package com.jhgsys.internal.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jhgsys.internal.common.entity.FebsConstant;
import com.jhgsys.internal.common.entity.QueryRequest;
import com.jhgsys.internal.common.utils.SortUtil;
import com.jhgsys.internal.system.dto.RoleDto;
import com.jhgsys.internal.system.dto.TenantDto;
import com.jhgsys.internal.system.entity.Menu;
import com.jhgsys.internal.system.entity.Role;
import com.jhgsys.internal.system.entity.RoleMenu;
import com.jhgsys.internal.system.entity.Tenant;
import com.jhgsys.internal.system.mapper.RoleMapper;
import com.jhgsys.internal.system.service.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author MrBird
 */
@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Autowired
    private IRoleMenuService roleMenuService;
    @Autowired
    private IMenuService menuService;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private ITenantService tenantService;
//    @Autowired
//    private ShiroRealm shiroRealm;

    @Override
    public List<Role> findUserRole(String username) {
        return this.baseMapper.findUserRole(username);
    }

    @Override
    public List<Role> findRoles(Role role) {
        return this.baseMapper.selectRoleList(role);
    }

    @Override
    public IPage<RoleDto> findRoles(Role role, QueryRequest request) {
        Page<RoleDto> page = new Page<>(request.getPageNum(), request.getPageSize());
        SortUtil.handlePageSort(request, page, "createdTime", FebsConstant.ORDER_DESC, true);
        IPage<RoleDto> pageData = this.baseMapper.findRolePage(page, role);
        List<RoleDto> roleList = pageData.getRecords();
        if (roleList != null && roleList.size() > 0) {
            roleList.forEach( r -> {
                List<Menu> menus = menuService.findRoleMenus(r.getRoleId());
                if (menus != null && menus.size() > 0) {
                    String menuStr = menus.stream().map(m -> m.getMenuId()).collect(Collectors.joining(","));
                    r.setMenuIds(menuStr);
                }
                //获取对应公司名称
                TenantDto tenant = tenantService.findTenantByTenantId(r.getTenantId());
                if(tenant != null){
                    r.setTenantName(tenant.getTenantName());
                }
            });
        }


        return pageData;
    }

    @Override
    public Role findByName(String roleName) {
        return this.baseMapper.selectOne(new QueryWrapper<Role>().lambda().eq(Role::getRoleName, roleName).last(" LIMIT 1 "));
    }

    @Override
    public RoleDto findRoleByRoleId(String roleId) {
        RoleDto roleDto = new RoleDto();
        Role role = this.baseMapper.selectById(roleId);
        if (role != null) {
            BeanUtils.copyProperties(role,roleDto);
            String tenantId = role.getTenantId();
            TenantDto tenantDto = tenantService.findTenantByTenantId(tenantId);
            if(null != tenantDto){
                roleDto.setTenantName(tenantDto.getTenantName());
            }
            List<Menu> menus = menuService.findRoleMenus(role.getRoleId());
//            List<Menu> menus = menuService.findTenantMenus(role.getTenantId());

            if (menus != null && menus.size() > 0) {
                //这里只取最后一级的menu，前端的树会自己把父选上
                Set<String> pidSet = menus.stream().map(Menu::getParentId).collect(Collectors.toSet());
                String menuStr = menus.stream().filter(m -> !pidSet.contains(m.getMenuId()))
                                      .map(m -> m.getMenuId()).collect(Collectors.joining(","));
                roleDto.setMenuIds(menuStr);
            }
        }
        return roleDto;
    }

    @Override
    public List<Tenant> getRoleTenantList(String tenantId) {
        if(StringUtils.isBlank(tenantId)){
            return tenantService.list(new LambdaQueryWrapper<Tenant>().eq(Tenant::getDeletedFlg, 0));
        }else {
            return tenantService.list(new LambdaQueryWrapper<Tenant>().eq(Tenant::getDeletedFlg, 0).eq(Tenant::getTenantId, tenantId));
        }
    }


    @Override
    @Transactional
    public void createRole(RoleDto role) {
        Role insertRole = new Role();
        BeanUtils.copyProperties(role,insertRole);
        role.setCreateTime(new Date());
        this.baseMapper.insert(insertRole);
        role.setRoleId(insertRole.getRoleId());
        this.saveRoleMenus(role);
    }

    @Override
    @Transactional
    public void updateRole(RoleDto role) {
        Role updateRole = new Role();
        BeanUtils.copyProperties(role,updateRole);
        role.setUpdatedTime(new Date());
        this.updateById(updateRole);
        List<String> roleIdList = new ArrayList<>();
        roleIdList.add(String.valueOf(role.getRoleId()));
        this.roleMenuService.deleteRoleMenusByRoleId(roleIdList);
        saveRoleMenus(role);

        //clearCache();
    }

    @Override
    @Transactional
    public void deleteRoles(String roleIds) {
        List<String> list = Arrays.asList(roleIds.split(StringPool.COMMA));
        this.baseMapper.delete(new QueryWrapper<Role>().lambda().in(Role::getRoleId, list));

        this.roleMenuService.deleteRoleMenusByRoleId(list);
        this.userRoleService.deleteUserRolesByRoleId(list);
    }

    /**
     * 新写的删除实现方法
     * @param roleIds
     * @param role
     */
    @Override
    @Transactional
    public void updateRoleDeletedFlg(String roleIds, Role role) {
        List<String> list = Arrays.asList(roleIds.split(StringPool.COMMA));
        LambdaUpdateWrapper<Role> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Role::getDeletedFlg,FebsConstant.INVALID);
        updateWrapper.in(Role::getRoleId,list);
        this.update(updateWrapper);
        this.roleMenuService.deleteRoleMenusByRoleId(list);
    }

    private void saveRoleMenus(RoleDto role) {
        if (StringUtils.isNotBlank(role.getMenuIds())) {
            String[] menuIds = role.getMenuIds().split(StringPool.COMMA);
            List<RoleMenu> roleMenus = new ArrayList<>();
            Arrays.stream(menuIds).forEach(menuId -> {
                RoleMenu roleMenu = new RoleMenu();
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleId(role.getRoleId());
                roleMenus.add(roleMenu);
            });
            roleMenuService.saveBatch(roleMenus);
        }
    }
}
